﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ttlang
{

    public class ProjectOption
    {
        public enum ProjectType
        {
            EXE,
            SHAREDLIB,
        }

        public class ProjectOutput
        {
            public string target;
            public bool autoBuild = false;
            public string outPath = "";
            public string tempPath = ";";
            public Newtonsoft.Json.Linq.JObject targetOptions;
            public void Parse(Newtonsoft.Json.Linq.JObject obj)
            {
                var ktarget = obj["target"]?.ToString();
                var kautoBuild = (bool?)obj["autoBuild"];
                var koutpath = obj["outPath"]?.ToString();
                var ktemppath = obj["tempPath"]?.ToString();
                if (ktarget == null || kautoBuild == null || koutpath == null)
                    throw new InvalidDataException();
                this.target = ktarget;

                Console.WriteLine("target : \t" + this.target);
                this.autoBuild = kautoBuild.Value;
                this.outPath = koutpath;
                this.tempPath = ktemppath;
                this.targetOptions = (Newtonsoft.Json.Linq.JObject?)obj["targetOptions"];
            }
        }
        public class CompilerOptions
        {
            public void Parse(Newtonsoft.Json.Linq.JObject obj)
            {
                //var joutputs = obj["outputs"] as Newtonsoft.Json.Linq.JArray;
                //if (joutputs == null) throw new InvalidDataException();
                //foreach (Newtonsoft.Json.Linq.JObject item in joutputs)
                //{
                //    if (item == null) throw new InvalidDataException();
                //    ProjectOutput output = new ProjectOutput();
                //    output.Parse(item);
                //    outputs.Add(output);
                //}
            }
            //public List<ProjectOutput> outputs = new List<ProjectOutput>();
        }
        public static ProjectOption LoadFrom(string filename)
        {
            ProjectOption op = new ProjectOption();
            //解析ttconfig.json 
            var json = Newtonsoft.Json.Linq.JObject.Parse(System.IO.File.ReadAllText(filename));
            var name = json["projectName"]?.ToString();
            var type = json["type"]?.ToString();
            if (name == null || type == null) throw new InvalidDataException();


            op.projectName = name;
            Enum.TryParse<ProjectType>(type, out op.type);

            {
                var option = json["compilerOptions"] as Newtonsoft.Json.Linq.JObject;
                if (option != null)
                    op.compilerOptions.Parse(option);
            }
            var path = System.IO.Path.GetDirectoryName(filename);
            Debug.Assert(path != null); //if (path == null) throw new InvalidDataException();用asseet 比throw 更有优势一点，在release可以移除这些检查代码
            op.proiectPath = System.IO.Path.GetFullPath(path);
            var files = System.IO.Directory.GetFiles(op.proiectPath, "*.tt", SearchOption.AllDirectories);
            var files2 = System.IO.Directory.GetFiles(op.proiectPath, "*.t", SearchOption.AllDirectories);
            int total = files.Length + files2.Length;
            op.projectfiles = new string[total];
            for (var i = 0; i < files.Length; i++)
            {
                op.projectfiles[i] = files[i].Substring(op.proiectPath.Length + 1);
            }
            for (var i = 0; i < files2.Length; i++)
            {
                op.projectfiles[files.Length + i] = files2[i].Substring(op.proiectPath.Length + 1);
            }
            return op;
        }
        public string proiectPath = "";
        public string[] projectfiles = new string[0];
        public string projectName = "";
        public ProjectType type;
        public CompilerOptions compilerOptions = new CompilerOptions();
    }
    public interface ICodeReader
    {
        string GetCode(string file);
    }

    public class CodeReader_FromFile : ICodeReader
    {
        ProjectOption option;
        public CodeReader_FromFile(ProjectOption option)
        {
            this.option = option;
        }

        public string GetCode(string file)
        {
            if (option.projectfiles.Contains(file) == false)
                throw new Exception("not have this file.");
            string filename = System.IO.Path.Combine(option.proiectPath, file);
            return System.IO.File.ReadAllText(filename);
        }
        public ProjectOption GetProjectOption()
        {
            return option;
        }
    }
}
